home *** CD-ROM | disk | FTP | other *** search
- /*
- * SimpleDrag.c Drag Manager sample program
- *
- * SimpleDrag lets the user make one or more picture windows
- * Pictures can be dragged among (amongst?) windows and from
- * PICT files
- *
- * All code using the Drag Manager is at the beginning of this
- * file (darn near, anyway)
- *
- * v 1.0d4 8/93 Greg Robbins
- *
- * 93/9 dj final touch up to match final interfaces:
- * Changed DragGetXXX -> GetDragXXX
- * Changed DragFlags -> DragAttributes and some flag names changed
- * Eliminated last parameter to GetFlavorData to match prototype
- *
- */
-
-
- #include "SimpleDrag.h" // nothing interesting is in SimpleDrag.h
-
- // menu constants
- #define kAppleMenuID 1
- #define kAboutMenuItem 1
- #define kFileMenuID 2
- #define kNewMenuItem 1
- #define kOpenMenuItem 2
- #define kCloseMenuItem 3
- #define kQuitMenuItem 5
-
-
-
- // general global variables
-
- Boolean gQuitFlag; // true when the app should exit the main event loop
-
- Boolean gHasColorQuickdrawFlag; // Gestalt info
-
- MenuHandle gAppleMenuHandle, gFileMenuHandle;
- unsigned short gWindowCounter;
-
- // data structure for each window
-
- typedef struct WindowData {
- PicHandle windowPic;
- };
- typedef struct WindowData WindowData, *WindowDataPtr, **WindowDataHandle;
-
-
- // global data for my Drag Manager handlers
-
- typedef struct DragHandlerGlobals {
- Boolean acceptableDragFlag;
- Boolean windowIsHilightedFlag;
- };
- typedef struct DragHandlerGlobals
- DragHandlerGlobals, *DragHandlerGlobalsPtr;
-
- DragHandlerGlobals gDragHandlerGlobals;
-
-
- /**************************************************************/
-
- /* This is the "aoce PhoneNumber" attribute type definition */
-
- AttributeType gWorkPhoneNumber = {smRoman,
- 16,
- {"aoce PhoneNumber"}
- };
- Str255 displayStr;
- #define MaxCharsPerLine 30
-
- DSSpec gTheCard;
- AuthIdentity gIdentity;
-
-
- /***************************************************
- * Drag support routines
- *
- * These are the installed drag handler routines
- * and supporting functions
- ***************************************************/
-
- // InstallDragHandlers attaches my tracking and receive handlers to
- // one of the application's windows
-
- OSErr InstallDragHandlers(WindowPtr theWindow)
- {
- // install our tracking and receive handlers for the window
-
- OSErr retCode;
-
- retCode = InstallTrackingHandler(MyTrackingHandler, theWindow, nil);
-
- if (retCode == noErr) {
- retCode = InstallReceiveHandler(MyReceiveHandler, theWindow, nil);
- if (retCode != noErr)
- (void) RemoveTrackingHandler(MyTrackingHandler, theWindow);
- }
-
- return retCode;
- }
-
-
- // RemoveDragHandlers removes my tracking and receive handlers from
- // one of the application's windows (prior to the window's disposal,
- // presumably)
-
- void RemoveDragHandlers(WindowPtr theWindow)
- {
- RemoveReceiveHandler(MyReceiveHandler, theWindow);
- RemoveTrackingHandler(MyTrackingHandler, theWindow);
- }
-
-
- // MouseInContentRgn returns true if the current mouse is in the content
- // area of the window (but not necessarily in the visible rgn)
-
- Boolean MouseIsInContentRgn(DragReference theDrag, WindowPtr theWindow)
- {
- Point mousePt;
-
- (void) GetDragMouse(theDrag, &mousePt, nil);
- return PtInRgn(mousePt, ((WindowPeek) theWindow)->contRgn);
- }
-
-
- // DragItemsAreAcceptable returns true if the contents (data) of
- // the drag are acceptable by a window of this application
- //
- // DragItemsAreAcceptable is called by the tracking and
- // receive handlers
-
- Boolean DragItemsAreAcceptable(DragReference theDrag)
- {
- OSErr retCode;
- unsigned short totalItems;
- ItemReference itemRef;
- Boolean acceptableFlag;
- HFSFlavor currHFSFlavor;
- Size flavorDataSize;
- FlavorFlags currFlavorFlags;
-
- acceptableFlag = false;
-
- // this app can only accept the drag of a single item
- retCode = CountDragItems(theDrag, &totalItems);
- if (retCode == noErr && totalItems == 1) {
-
- // get the reference number of the dragged item
- retCode = GetDragItemReferenceNumber(theDrag, 1, &itemRef);
- if (retCode == noErr) {
-
- // use GetFlavorFlags to check on flavor existence of PICT data
- // without forcing translation
-
- retCode = GetFlavorFlags (theDrag, itemRef, 'PICT', &currFlavorFlags);
- if (retCode == noErr)
- acceptableFlag = true;
- // Drags from any AOCE Catalog are ok
- else if ( retCode = GetFlavorFlags (theDrag, itemRef, flavorTypeDirectory, &currFlavorFlags) == noErr )
- acceptableFlag = true;
-
- else {
-
- // check if the item is a file spec for a PICT file or an AOCE business card
- flavorDataSize = sizeof(HFSFlavor);
- retCode = GetFlavorData(theDrag, itemRef, flavorTypeHFS, &currHFSFlavor,
- &flavorDataSize, 0);
- // Is it a business card?
- if (retCode == noErr && (currHFSFlavor.fileType == 'PICT' ||
- currHFSFlavor.fileType == kBusinessCardFileType))
- acceptableFlag = true;
- }
- }
- }
- return acceptableFlag;
- }
-
-
- // DragIsNotInSourceWindow returns true if the drag in progress
- // is not in the same window it originated in
- //
- // DragIsNotInSourceWindow is called by the tracking and receive handlers
- //
- // Note that, if this application allowed items to be dragged within
- // its windows, this function would not be appropriate.
- // Instead, hilighting would probably occur in the source window
- // when the dragHasLeftSourceWindow flag is set, and the receive
- // handler wouldn't check this at all
-
- Boolean DragIsNotInSourceWindow(DragReference theDrag)
- {
- DragAttributes currDragFlags;
-
- (void) GetDragAttributes(theDrag, &currDragFlags);
- return ((currDragFlags & dragInsideSenderWindow) == 0);
- }
-
-
- // MyTrackingHandler is called by the drag manager whenever a drag is
- // over one of the application's windows
- //
- // upon entry, the current port has been set to theWindow by the Drag Manager
-
- pascal OSErr MyTrackingHandler(DragTrackingMessage theMessage, WindowPtr theWindow,
- void *handlerRefCon, DragReference theDrag)
- {
- #pragma unused (handlerRefCon)
-
- RgnHandle tempRgn;
- Boolean mouseInContentFlag;
- OSErr retCode;
-
- retCode = noErr;
-
- switch (theMessage) {
-
- case dragTrackingEnterHandler:
-
- // determine if the items are acceptable and store
- // that flag in the globals, plus reset the
- // hilighted global flag
-
- gDragHandlerGlobals.acceptableDragFlag =
- DragItemsAreAcceptable(theDrag);
- gDragHandlerGlobals.windowIsHilightedFlag = false;
-
- // let the drag manager know if we can't accept this drag
- if (!gDragHandlerGlobals.acceptableDragFlag)
- retCode = dragNotAcceptedErr;
- break;
-
- case dragTrackingEnterWindow:
- case dragTrackingInWindow:
- case dragTrackingLeaveWindow:
-
- // highlighting of the window during a drag is done
- // here. Do it only if we can accept these items
- // and we're not in the source window...
-
- if (gDragHandlerGlobals.acceptableDragFlag &&
- DragIsNotInSourceWindow(theDrag)) {
-
- // unless the mouse is leaving the visible area of the
- // window, check if it's in the window's content region
-
- if (theMessage == dragTrackingLeaveWindow)
- mouseInContentFlag = false;
-
- else
- mouseInContentFlag = MouseIsInContentRgn(theDrag, theWindow);
-
- // if the mouse is in the content area and the window
- // is not yet hilighted, then do the hilighting
-
- if (mouseInContentFlag &&
- !gDragHandlerGlobals.windowIsHilightedFlag) {
-
- // set the proper clip
- ClipRect(&theWindow->portRect);
-
- // make a region bordering the window content
- tempRgn = NewRgn();
- RectRgn(tempRgn, &theWindow->portRect);
-
- // draw the hilight
- if (ShowDragHilite(theDrag, tempRgn, true) == noErr)
-
- // remember that hilighting is now on
- gDragHandlerGlobals.windowIsHilightedFlag = true;
-
- // free up the region
- DisposeRgn(tempRgn);
- }
-
- // else if the mouse is not in the content region
- // and the window is hilighted, erase the hilight
-
- else if (!mouseInContentFlag &&
- gDragHandlerGlobals.windowIsHilightedFlag) {
-
- // set the proper clip
- ClipRect(&theWindow->portRect);
-
- // erase the hilight and restore the port
- if (HideDragHilite(theDrag) == noErr)
-
- // remember that hilighting is now off
- gDragHandlerGlobals.windowIsHilightedFlag = false;
- }
- }
- break;
-
- // do nothing for the leaveHandler message
- case dragTrackingLeaveHandler:
- break;
-
- // let the drag manager know if we didn't recognize the message
- default:
- retCode = paramErr;
- }
-
- return retCode;
- }
-
-
-
- /*****************************************************************************
- * ClearMemory
- * This is a utility function that clears a block of memory. It isn't very
- * efficient. It us normally called by executing the CLEAR macro which expands
- * CLEAR(thing) to
- * ClearMemory(&thing, sizeof thing);
- *****************************************************************************/
- void
- ClearMemory(
- void *recordPtr,
- register Size recordSize
- )
- {
- register char *rp;
-
- rp = (char *) recordPtr;
- while (recordSize > 0) {
- *rp++ = 0;
- --recordSize;
- }
- }
-
-
-
-
- /*****************************************************************
- * GetRecordID
- *
- *
- *****************************************************************/
-
- OSErr GetRecordID( FSSpecPtr fsspec,
- RecordIDPtr ridPtr,
- RStringPtr recordType)
- {
- OSErr err;
- DirParamBlock pb;
-
- pb.openPersonalDirectoryPB.fsSpec = fsspec;
- pb.openPersonalDirectoryPB.accessRequested = fsRdPerm;
- /* get reference number for Business Card */
- err = DirOpenPersonalDirectory(&pb);
- if (err == noErr)
- {
- err = DoEnumerateGet( pb.openPersonalDirectoryPB.dsRefNum,
- (long)&ridPtr->local,
- recordType,
- gIdentity);
- if (err == noErr)
- {
- pb.getNameAndTypePB.identity = 0;
- pb.getNameAndTypePB.aRecord = ridPtr;
- err = DirGetNameAndType (&pb, false);
- if (err == noErr)
- {
- pb.makePersonalDirectoryRLIPB.fromFSSpec = fsspec;
- pb.makePersonalDirectoryRLIPB.pRLIBufferSize = kRLIMaxBytes;
- pb.makePersonalDirectoryRLIPB.pRLI = ridPtr->rli;
- err = DirMakePersonalDirectoryRLI(&pb);
- }
- }
- DirClosePersonalDirectory(&pb);
- }
-
- return (err);
- }
-
-
-
- // MyReceiveHandler is called by the drag manager whenever a drag is
- // ends on one of the application's windows
-
- pascal OSErr MyReceiveHandler(WindowPtr theWindow, void *handlerRefCon,
- DragReference theDrag)
- {
- #pragma unused (handlerRefCon)
- ItemReference itemRef;
- Size dataSize;
- Handle tempHandle;
- HFSFlavor theHFSFlavor;
- Boolean dataObtainedFlag;
- OSErr retCode;
- // AttributeTypePtr theAttrType;
- PackedDSSpec packedDSSpec;
- Attribute attribute;
- DSSpec dsspec;
- RecordID rid;
- short dsRefNum;
- HFSFlavor hfsData;
- RString name,type;
- PackedRLI packedRLI;
- LocalRecordID localRID;
- CreationID cid;
-
-
- dataObtainedFlag = false;
- if (!DragItemsAreAcceptable(theDrag) ||
- !MouseIsInContentRgn(theDrag, theWindow) ||
- !DragIsNotInSourceWindow(theDrag))
- return dragNotAcceptedErr;
-
- // There is only one item, so get its reference number.
- retCode = GetDragItemReferenceNumber(theDrag, 1, &itemRef);
- if (retCode != noErr)
- return retCode;
-
-
-
- // PICT data is preferred, so get it if it's available.
- retCode = GetFlavorDataSize(theDrag, itemRef, 'PICT', &dataSize);
- if (retCode == noErr) {
- tempHandle = TempNewHandle(dataSize, &retCode);
- if (tempHandle == nil) {
- tempHandle = NewHandle(dataSize);
- }
- if (tempHandle != nil) {
- HLock(tempHandle);
- retCode = GetFlavorData(theDrag, itemRef, 'PICT', *tempHandle,
- &dataSize, 0);
- if (retCode == noErr) {
- retCode = SetWindowPicture(theWindow, (PicHandle) tempHandle);
- if (retCode == noErr)
- dataObtainedFlag = true;
-
-
- }
- DisposeHandle(tempHandle);
- }
- }
-
-
-
- // Check for a Business Card that is *not* in a personal catalog (i.e. somewhere
- // on the users hard disk.
-
- retCode = GetFlavorDataSize(theDrag, itemRef, flavorTypeHFS, &dataSize);
- if (retCode == noErr)
- {
- retCode = GetFlavorData(theDrag, itemRef, flavorTypeHFS, &hfsData,
- &dataSize, 0);
- if (retCode == noErr)
- {
- if (DoAuthentication() == noErr)
- {
- name.dataLength = kRStringMaxBytes;
- type.dataLength = kRStringMaxBytes;
- OCENewLocalRecordID(&name,&type,&cid,&localRID);
- OCENewRecordID(&packedRLI,&localRID,&rid);
-
- /* Convert a FSSpec to a RecordID */
- retCode = GetRecordID(&hfsData.fileSpec,
- &rid,
- OCEGetIndRecordType(kBusinessCardRecTypeNum));
-
-
- /* Now that we have the RecordID, we could easily
- create a DSSpec structure by adding the extension part
- (which is null) as follows:
-
- DSSpec theDSSpec;
-
- theDSSpec.extensionType = kOCEentnDSSpec;
- theDSSpec.extensionSize = 0;
- theDSSpec.extensionValue = NULL;
- theDSSpec.entitySpecifier = &rid;
-
- To create a packedDSSpec from this, we would do the
- following:
-
- PackedDSSpecPtr thePackedSpecPtr;
- unsigned short packedSpecSize = OCEPackedDSSpecSize(&theDSSpec);
-
- thePackedSpecPtr = (PackedDSSpecPtr)NewPtr(packedSpecSize);
- if (thePackedSpecPtr != NULL)
- retCode = OCEPackDSSpec(&theDSSpec, thePackedSpecPtr, packedSpecSize);
- */
-
- if (retCode == noErr)
- {
- retCode = OpenPersonalCatalog(rid.rli,
- &dsRefNum);
- if (retCode == noErr)
- {
- retCode = GetAttributeFromRID ( &rid,
- dsRefNum,
- &gWorkPhoneNumber,
- &attribute,
- gIdentity);
- if (retCode == noErr)
- {
- if (OCEEqualRString((RStringPtr)&gWorkPhoneNumber,
- (RStringPtr)&attribute.attributeType,
- kOCEAttrType) == true)
- DrawPhoneNumberAttribute(theWindow,&attribute.value);
- else
- myReportStringInWindow(theWindow,"\pNo Work Phone Number attribute.");
-
- }
- }
- }
- }
- SysBeep(20);
- SysBeep(20);
- SysBeep(20);
- dataObtainedFlag = true;
-
- }
- else
- DebugStr("\pGetting flavor data for dir failed");
- }
- else
- {
- // Check for items that were dragged from within an AOCE catalog
-
- retCode = GetFlavorDataSize(theDrag, itemRef, flavorTypeDirectory, &dataSize);
- if (retCode == noErr)
- {
-
- retCode = GetFlavorData(theDrag, itemRef, flavorTypeDirectory, &packedDSSpec,
- &dataSize, 0);
- if (retCode == noErr)
- {
- retCode = DoAuthentication();
- if (retCode == noErr)
- {
-
- // In our example, we are only interested in the attribute type
- // "aoce PhoneNumber". However, we could retrieve the data from
- // any attribute type we want. You can get the standard attribute
- // types using the OCEGetIndAttributeType call shown below.
- //
- // theAttrType = OCEGetIndAttributeType(kMailSlotsAttrTypeNum);
-
- OCEUnpackDSSpec(&packedDSSpec, &dsspec, &rid);
- retCode = OpenPersonalCatalog(rid.rli,&dsRefNum);
- if (retCode == noErr || retCode == kOCEMiscError)
- {
- retCode = GetAttributeFromRID ( &rid,
- dsRefNum,
- &gWorkPhoneNumber/*theAttrType*/,
- &attribute,
- gIdentity);
-
- if (retCode == noErr)
- {
- if (OCEEqualRString((RStringPtr)&gWorkPhoneNumber,
- (RStringPtr)&attribute.attributeType,
- kOCEAttrType) == true)
- DrawPhoneNumberAttribute(theWindow,&attribute.value);
- else
- myReportStringInWindow(theWindow,"\pNo Work Phone Number attribute.");
- }
- else
- myReportStringInWindow(theWindow,"\pCould not get Work Phone Number attribute.");
- }
-
- }
-
- SysBeep(20);
- SysBeep(20);
- SysBeep(20);
- dataObtainedFlag = true;
-
- }
- else
- DebugStr("\pGetting flavor data for dir failed");
- }
-
- }
-
-
- if (!dataObtainedFlag) {
- // Couldn't get PICT data so try to get HFS-flavor data.
- dataSize = sizeof(HFSFlavor);
- retCode = GetFlavorData(theDrag, itemRef, flavorTypeHFS,
- &theHFSFlavor, &dataSize, 0);
- if (retCode == noErr && theHFSFlavor.fileType == 'PICT') {
- retCode = SetWindowPictureFromFile(&theHFSFlavor.fileSpec, theWindow);
- }
- }
- /*
- if (retCode != noErr)
- (void) ReportErrorInWindow(nil,"\pCannot display received picture. ", retCode);
- */
-
- return retCode;
- }
-
-
-
-
-
-
-
-
-
- // *****************************************************************
- // * GetIdentity
- // *
- // * authenticate the user
- // *****************************************************************
- OSErr GetIdentity()
- {
- OSErr err;
- SDPIdentityKind selectedKind;
-
- err = SDPPromptForID(&gIdentity,
- NULL,
- NULL,
- "\pPlease enter the password for your master key",
- OCEGetIndRecordType(kUserRecTypeNum),
- kSDPLocalIdentityMask,
- &selectedKind,
- NULL,
- 0); /* ignored */
- return err;
- }
-
-
- // *****************************************************************
- // * DoAuthentication
- // *
- // * check for user authentication
- // *****************************************************************
- OSErr DoAuthentication()
- {
- OSErr err;
- AuthGetLocalIdentityPB pb;
-
- // first check if the user has already been authenticated. If so
- // we dont want to bother with authenticating again.
- err = AuthGetLocalIdentity((AuthParamBlockPtr)&pb,false);
-
- if (err != noErr)
- // user has not been authenticated, so let's do it now
- err = GetIdentity();
- else
- // user has already been authenticated
- gIdentity = pb.theLocalIdentity;
-
- return err;
- }
-
- // *****************************************************************
- // * myDrawRString
- // *
- // * Hack routine that prints an RString value in a window
- // *
- // *****************************************************************
-
- myDrawRString(RStringPtr theRString, short *xCoord, short *yCoord)
- {
- short index;
- short byteCount;
-
- index = 0;
- MoveTo(*xCoord,*yCoord);
- while (index < theRString->dataLength)
- {
- byteCount = MaxCharsPerLine;
- if ((theRString->dataLength - index) < MaxCharsPerLine)
- byteCount = (theRString->dataLength - index);
-
- DrawText((Ptr)&theRString->body,index,byteCount);
- index = index + MaxCharsPerLine;
- *yCoord += 10;
- MoveTo(*xCoord,*yCoord);
-
- }
-
- }
-
- void myReportStringInWindow(WindowPtr theWindow,
- StringPtr theString)
- {
- PicHandle tempPic;
- GrafPtr savePort;
-
- GetPort(&savePort);
- SetPort(theWindow);
-
- tempPic = OpenPicture(&theWindow->portRect);
- MoveTo(20, theWindow->portRect.bottom / 3);
- TextFont(systemFont);
- DrawString(theString);
- ClosePicture();
- SetWindowPicture(theWindow, tempPic);
- KillPicture(tempPic);
-
- SetPort(savePort);
- }
-
-
-
- // *****************************************************************
- // * DrawPhoneNumberAttribute
- // *
- // * The "aoce PhoneNumber" value data is two RStrings packed
- // * together one right after the other (type followed by the actual number).
- // * This is a hack routine that displays both of the strings.
- // *
- // *****************************************************************
-
- void DrawPhoneNumberAttribute(WindowPtr theWindow,
- AttributeValuePtr theAttrValue)
- {
- RStringPtr valueDataPtr;
- StringPtr workStr,phoneNumStr;
- Ptr p;
-
-
- valueDataPtr = (RStringPtr)theAttrValue->bytes;
- workStr = OCERToPString(valueDataPtr);
- BlockMove(workStr,&displayStr,*workStr+1);
-
- /* next string is packed right after the first one */
- p = (Ptr)(&valueDataPtr->body[0] + valueDataPtr->dataLength);
- valueDataPtr = (RStringPtr)p;
- phoneNumStr = OCERToPString(valueDataPtr);
-
- ConcatPascalStrings(displayStr, phoneNumStr);
- myReportStringInWindow(theWindow,displayStr);
- }
-
-
- // OutlineRegion changes a region into a tracing of its border
- // which is appropriate for normal dragging
- //
- // OutlineRegion is called by DoWindowContentDrag
-
- void OutlineRegion(RgnHandle theRgn)
- {
- RgnHandle tempRgn;
-
- tempRgn = NewRgn();
- CopyRgn(theRgn, tempRgn);
- InsetRgn(tempRgn, 1, 1);
- DiffRgn(theRgn, tempRgn, theRgn);
- DisposeRgn(tempRgn);
- }
-
-
- // DoWindowContentDrag is called by the application whenever a drag
- // begins on one of the app's windows
-
- OSErr DoWindowContentDrag(WindowPtr theWindow, EventRecord *theEvent)
- {
- OSErr retCode;
- DragReference theDrag;
- Rect dragBounds;
- RgnHandle dragRgn;
- ItemReference theItem;
- short mouseUpModifiers;
- DragAttributes currDragFlags;
-
- // create a new drag
- retCode = NewDrag(&theDrag);
- if (retCode != noErr) goto Bail;
-
- // use the window ptr as item reference for the heck of it
- theItem = (ItemReference) theWindow;
-
- if ( KeyIsDown(0x37) == false )
- {
- PicHandle windowPicHandle;
-
- // add the picture data to the drag
- windowPicHandle = GetWindowPicture(theWindow);
- HLock((Handle) windowPicHandle);
-
- retCode = AddDragItemFlavor(theDrag, theItem, 'PICT',
- (Ptr) *windowPicHandle,
- GetHandleSize((Handle) windowPicHandle), 0);
-
- HUnlock((Handle) windowPicHandle);
- }
- else
- {
- PackedDSSpecPtr thePackedSpec;
- unsigned short packedSpecSize = OCEPackedDSSpecSize(&gTheCard);
-
- if ( packedSpecSize == 0 )
- DebugStr("\pIt's zero length");
-
- thePackedSpec = (PackedDSSpecPtr)NewPtr(packedSpecSize);
-
- retCode = OCEPackDSSpec(&gTheCard, thePackedSpec, packedSpecSize);
-
- if ( retCode != noErr )
- {
- DebugStr("\pPacking Failed");
- goto DisposeDragAndBail;
- }
- retCode = AddDragItemFlavor(theDrag, theItem, flavorTypeDirectory, (Ptr)&thePackedSpec, kPackedDSSpecMaxBytes, 0);
- if ( retCode != noErr )
- {
- DebugStr("\pAdding Item failed");
- goto DisposeDragAndBail;
- }
- }
- if (retCode != noErr) goto DisposeDragAndBail;
-
- // generate the bounds and region for the drag using the window's
- // content rectangle
- dragBounds = (**((WindowPeek) theWindow)->contRgn).rgnBBox;
- retCode = SetDragItemBounds(theDrag, theItem, &dragBounds);
- if (retCode != noErr) goto DisposeDragAndBail;
-
- dragRgn = NewRgn();
- RectRgn(dragRgn, &dragBounds);
- OutlineRegion(dragRgn);
-
- // do the drag and clean up
- retCode = TrackDrag(theDrag, theEvent, dragRgn);
-
- DisposeRgn(dragRgn);
-
- if (retCode == noErr) {
-
- // the drag was successful
-
- // if the option key was not pressed at mouseUp and the drag ended
- // in the source application then this is a move operation and we
- // have to clear the source window
-
- (void) GetDragModifiers(theDrag, nil, nil, &mouseUpModifiers);
-
- (void) GetDragAttributes(theDrag, &currDragFlags);
-
- if ((mouseUpModifiers & optionKey) == 0 &&
- (currDragFlags & dragInsideSenderApplication) != 0)
-
- (void) SetEmptyWindowPicture(theWindow);
- }
-
- DisposeDragAndBail:
- DisposeDrag(theDrag);
-
- Bail:
- return retCode;
- }
-
-
-
- /***************************************************
- * Apple Event routines
- *
- * These routines handle the required Apple events
- ***************************************************/
-
- pascal OSErr DoAEOpenApplication(AppleEvent * theAppleEvent,
- AppleEvent * replyAppleEvent,
- long refCon)
- {
- #pragma unused (theAppleEvent, replyAppleEvent, refCon)
-
- // make an empty window
- (void) DoNewWindow();
- return noErr;
- }
-
- pascal OSErr DoAEOpenDocuments(AppleEvent * theAppleEvent,
- AppleEvent * replyAppleEvent,
- long refCon)
- {
- #pragma unused (replyAppleEvent, refCon)
- OSErr retCode;
- FSSpec currSpec;
- AEDescList docDescList;
- long itemCount, index;
- AEKeyword keyword;
- DescType typeCode;
- Size actualSize;
-
- // retrieve all documents from the Apple event and open them
- retCode = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList,
- &docDescList);
- if (retCode != noErr) goto Bail;
-
- retCode = AECountItems(&docDescList, &itemCount);
- if (retCode != noErr) goto DisposeDocDescListAndBail;
-
- for (index = 1; index <= itemCount; index++) {
- retCode = AEGetNthPtr(&docDescList, index, typeFSS,
- &keyword, &typeCode, (Ptr) &currSpec, sizeof(FSSpec),
- &actualSize);
- if (retCode != noErr) goto DisposeDocDescListAndBail;
-
- (void) OpenPictureInNewWindow(&currSpec);
- }
-
- DisposeDocDescListAndBail:
- (void) AEDisposeDesc(&docDescList);
-
- Bail:
- if (retCode == noErr) return noErr;
- else return errAEEventNotHandled;
- }
-
- pascal OSErr DoAEQuitApplication(AppleEvent * theAppleEvent,
- AppleEvent * replyAppleEvent,
- long refCon)
- {
- #pragma unused (theAppleEvent, replyAppleEvent, refCon)
-
- DoQuit(); // set the quit flag (doesn't immediately quit)
- return noErr;
- }
-
- void DoHighLevelEvent(EventRecord * theEventRecPtr)
- // high-level event dispatching
- {
- (void) AEProcessAppleEvent(theEventRecPtr);
- }
-
- OSErr InstallAppleEventHandlers()
- {
- OSErr retCode;
-
- retCode = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
- /*(AEEventHandlerProcPtr)*/(EventHandlerProcPtr) DoAEOpenApplication, 0, false);
-
- if (retCode == noErr)
- retCode = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
- /*(AEEventHandlerProcPtr)*/(EventHandlerProcPtr) DoAEOpenDocuments, 0, false);
-
- if (retCode == noErr)
- retCode = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
- /*(AEEventHandlerProcPtr)*/(EventHandlerProcPtr) DoAEQuitApplication, 0, false);
-
- return retCode;
- }
-
-
- /***************************************************
- * general application utility routines
- ***************************************************/
-
- // ConcatPascalStrings concatenates s2 to the end of s1
- void ConcatPascalStrings(StringPtr s1, StringPtr s2)
- {
- short s1Length, s2Length;
-
- s1Length = s1[0];
- s2Length = s2[0];
- BlockMove(&s2[1], &s1[s1Length+1], s2Length);
- s1[0] = s1Length + s2Length;
- }
-
- // GetApplicationName uses the Process Manager to find
- // the current app's name
- OSErr GetApplicationName(StringPtr appNameString)
- {
- ProcessInfoRec appPIR;
- ProcessSerialNumber appPSN;
-
- appPSN.lowLongOfPSN = kCurrentProcess;
- appPSN.highLongOfPSN = 0;
-
- appPIR.processInfoLength = sizeof(ProcessInfoRec);
- appPIR.processAppSpec = nil;
- appPIR.processName = appNameString;
-
- return GetProcessInformation(&appPSN, &appPIR);
- }
-
-
- /***************************************************
- * routines for dealing with the window pictures
- ***************************************************/
-
- // GetWindowPicture returns the handle of a window's picture
-
- PicHandle GetWindowPicture(WindowPtr theWindow)
- {
- WindowDataHandle windowData;
-
- windowData = (WindowDataHandle) GetWRefCon(theWindow);
- return (**windowData).windowPic;
- }
-
-
- // SetWindowPicture copies thePicture into the existing windowPic
- // handle of theWindow's data. If the copy is successful,
- // the window is invalidated to force it to be redrawn
-
- OSErr SetWindowPicture(WindowPtr theWindow, PicHandle newPicture)
- {
- PicHandle windowPic;
- Size picSize;
- GrafPtr savePort;
- OSErr retCode;
-
- // get the old picture handle
- windowPic = GetWindowPicture(theWindow);
-
- // resize the old handle to hold the new picture
- picSize = GetHandleSize((Handle) newPicture);
- SetHandleSize((Handle) windowPic, picSize);
- retCode = MemError();
- if (retCode == noErr) {
-
- // copy the picture and invalidate the window
- BlockMove(*newPicture, *windowPic, picSize);
-
- GetPort(&savePort);
- SetPort(theWindow);
- InvalRect(&theWindow->portRect);
- SetPort(savePort);
- }
- return retCode;
- }
-
-
- // SetEmptyWindowPicture replaces the existing picture handle
- // for a window with a new, empty one
-
- OSErr SetEmptyWindowPicture(WindowPtr theWindow)
- {
- PicHandle emptyPicture;
-
- // make a new, empty picture handle
- emptyPicture = (PicHandle) NewHandleClear(sizeof(Picture));
-
- if (emptyPicture != nil)
-
- // replace the window's picture with the empty picture
- return SetWindowPicture(theWindow, emptyPicture);
-
- else
- return MemError();
- }
-
-
- // SetWindowPictureFromFile reads the PICT file specified by pictSpec
- // and replaces the window's picture with the new one
-
- OSErr SetWindowPictureFromFile(FSSpecPtr pictSpec, WindowPtr theWindow)
- {
- OSErr retCode;
- short pictRefNum;
- long fileLength;
- Size pictSize;
- Handle tempHandle;
-
- pictRefNum = 0;
- tempHandle = nil;
-
- // open the file and find its size
- retCode = FSpOpenDF(pictSpec, fsRdPerm, &pictRefNum);
- if (retCode != noErr) goto Bail;
-
- retCode = GetEOF(pictRefNum, &fileLength);
- if (retCode != noErr) goto Bail;
-
- // skip over 512-byte pict file header
- retCode = SetFPos(pictRefNum, fsFromMark, 512);
- if (retCode != noErr) goto Bail;
-
- pictSize = fileLength - 512;
-
- // allocate a buffer for the file's picture data,
- // in temp memory if it is available
- tempHandle = TempNewHandle(pictSize, &retCode);
- if (tempHandle == nil) {
- tempHandle = NewHandle(pictSize);
- retCode = MemError();
- }
- if (tempHandle == nil) goto Bail;
-
- // read in the picture data
- HLock(tempHandle);
- retCode = FSRead(pictRefNum, &pictSize, *tempHandle);
- HUnlock(tempHandle);
- if (retCode != noErr) goto Bail;
-
- // replace the window's picture with the new data
- retCode = SetWindowPicture(theWindow, (PicHandle) tempHandle);
-
- Bail:
- if (pictRefNum != 0) FSClose(pictRefNum);
- if (tempHandle != nil) DisposeHandle(tempHandle);
-
- return retCode;
- }
-
-
- // OpenPictureInNewWindow creates a new window and sets its
- // picture to be the one contained in the specified PICT file
- // If the file cannot be read, an error message is displayed
- // in the window instead
-
- WindowPtr OpenPictureInNewWindow(FSSpecPtr fileSpec)
- {
- WindowPtr theWindow;
- OSErr retCode;
-
- theWindow = DoNewWindow();
- if (theWindow != nil) {
-
- retCode = SetWindowPictureFromFile(fileSpec, theWindow);
- if (retCode != noErr) {
- (void) ReportErrorInWindow(theWindow,
- "\pCannot display opened picture. ", retCode);
- }
- }
- return theWindow;
- }
-
-
- // DrawWindow draws a window's picture in the window
-
- void DrawWindow(WindowPtr theWindow)
- {
- PicHandle windowPic;
- Rect tempRect;
-
- windowPic = GetWindowPicture(theWindow);
-
- if (windowPic != nil) {
- tempRect = (**windowPic).picFrame;
- DrawPicture(windowPic, &tempRect);
- }
- }
-
- // ReportErrorInWindow draws a string and a number in the specified window
- // if theWindow is nil, a new window is created and its WindowPtr is returned
-
- WindowPtr ReportErrorInWindow(WindowPtr theWindow, StringPtr theString,
- OSErr errNum)
- {
- Str255 copyStr;
- Str15 numStr;
-
- BlockMove(theString, copyStr, theString[0]+1);
- NumToString(errNum, numStr);
- ConcatPascalStrings(copyStr, numStr);
- return ReportStringInWindow(theWindow, copyStr);
- }
-
- // ReportStringInWindow draws a string in the specified window
- // if theWindow is nil, a new window is created and its WindowPtr is returned
-
- WindowPtr ReportStringInWindow(WindowPtr theWindow, StringPtr theString)
- {
- PicHandle tempPic;
- GrafPtr savePort;
-
- if (theWindow == nil)
- theWindow = DoNewWindow();
-
- if (theWindow != nil) {
- GetPort(&savePort);
- SetPort(theWindow);
-
- tempPic = OpenPicture(&theWindow->portRect);
- MoveTo(20, theWindow->portRect.bottom / 3);
- TextFont(systemFont);
- DrawString(theString);
- ClosePicture();
- SetWindowPicture(theWindow, tempPic);
- KillPicture(tempPic);
-
- SetPort(savePort);
- }
- return theWindow;
- }
-
-
- /***************************************************
- * typical Mac toolbox routines
- ***************************************************/
-
- // CreateMenus makes menus the old-fashioned way
- void CreateMenus()
- {
- // create Apple menu
- gAppleMenuHandle = NewMenu(kAppleMenuID, "\p\024");
- AppendMenu(gAppleMenuHandle, "\pAbout SimpleDrag...;(-");
- AddResMenu(gAppleMenuHandle, 'DRVR');
- InsertMenu(gAppleMenuHandle, 0);
-
- // create File menu
- gFileMenuHandle = NewMenu(kFileMenuID, "\pFile");
- AppendMenu(gFileMenuHandle, "\pNew/N;Open.../O;Close/W;(-;Quit/Q");
- InsertMenu(gFileMenuHandle, 0);
-
- DrawMenuBar();
- }
-
- // DoOpen displays a standard file dialog and, if the user selects
- // a PICT file, opens the file in a new window
- void DoOpen()
- {
- StandardFileReply fileSFR;
- SFTypeList sfTypes;
-
- sfTypes[0] = 'PICT';
-
- StandardGetFile(nil, 1, sfTypes, &fileSFR);
- if (fileSFR.sfGood)
- (void) OpenPictureInNewWindow(&fileSFR.sfFile);
- }
-
-
- // DoNewWindow creates a new window with an empty picture
- // and returns the window's WindowPtr
-
- WindowPtr DoNewWindow()
- {
- WindowPtr newWindow;
- Str63 windowNameStr;
- Str15 numStr;
- WindowDataHandle newWindowDataHandle;
- Rect windowRect;
- OSErr retCode;
-
- // one more window in the world
- gWindowCounter++;
-
- // find a size and place for the new window
- windowRect = qd.screenBits.bounds;
- SetRect(&windowRect, windowRect.left, windowRect.top + 40,
- windowRect.right / 2, windowRect.bottom / 2);
- OffsetRect(&windowRect, 20 * (gWindowCounter % 10), 20 * (gWindowCounter % 10));
-
- // make a name for the window by concatenating gWindowCounter to the app name
- NumToString(gWindowCounter, numStr);
- if (GetApplicationName(windowNameStr) != noErr)
- *windowNameStr = 0;
- ConcatPascalStrings(windowNameStr, "\p ");
- ConcatPascalStrings(windowNameStr, numStr);
-
- // open the window
- if (gHasColorQuickdrawFlag)
- newWindow = NewCWindow(nil, &windowRect, windowNameStr, true,
- documentProc, (WindowPtr) -1, true, 0);
- else
- newWindow = NewWindow(nil, &windowRect, windowNameStr, true,
- documentProc, (WindowPtr) -1, true, 0);
-
- if (newWindow == nil) goto Bail;
-
- SetPort(newWindow);
- ClipRect(&newWindow->portRect);
-
- // attach my drag handlers to this window
-
- if ((retCode = InstallDragHandlers(newWindow)) != noErr)
- {
- if ( retCode == duplicateHandlerErr )
- RemoveDragHandlers(newWindow);
- goto DisposeWindowAndBail;
- }
- // allocate a data structure and a blank picture for the window
-
- newWindowDataHandle = (WindowDataHandle) NewHandle(sizeof(WindowData));
- if (newWindowDataHandle == nil) goto RemoveHandlersAndBail;
-
- (**newWindowDataHandle).windowPic =
- (PicHandle) NewHandleClear(sizeof(Picture));
- if ((**newWindowDataHandle).windowPic == nil) {
- DisposeHandle((Handle) newWindowDataHandle);
- goto RemoveHandlersAndBail;
- }
-
- SetWRefCon(newWindow, (long) newWindowDataHandle);
-
- return newWindow;
-
- RemoveHandlersAndBail:
- RemoveDragHandlers(newWindow);
-
- DisposeWindowAndBail:
- DisposeWindow(newWindow);
-
- Bail:
- gWindowCounter--;
- return nil;
-
- }
-
- // DoCloseWindow disposes of a window and does all necessary clean-up
- void DoCloseWindow(WindowPtr theWindow)
- {
- if (theWindow != nil) {
- KillPicture(GetWindowPicture(theWindow));
- DisposeHandle((Handle) GetWRefCon(theWindow));
- RemoveDragHandlers(theWindow);
- DisposeWindow(theWindow);
- }
- }
-
- // DoQuit closes all open windows and sets the global quit flag
- void DoQuit()
- {
- while (FrontWindow() != nil)
- DoCloseWindow(FrontWindow());
- gQuitFlag = true;
- }
-
- // DoAboutWindow just raises a new window and displays my name
- WindowPtr DoAboutWindow()
- {
- return ReportStringInWindow(nil, "\pSimpleDrag by Greg Robbins July 1993");
- }
-
- // DoMenuCommand handles user menu selections
- void DoMenuCommand(long menuVal)
- {
- short theItem, theMenu;
- Str255 deskAccessoryName;
-
- theItem = LoWord(menuVal);
- theMenu = HiWord(menuVal);
-
- switch (theMenu) {
-
- case kAppleMenuID:
- if (theItem == kAboutMenuItem)
- (void) DoAboutWindow();
-
- else {
- GetItem(gAppleMenuHandle, theItem, deskAccessoryName);
- (void) OpenDeskAcc(deskAccessoryName);
- }
- break;
-
- case kFileMenuID:
-
- if (theItem == kNewMenuItem)
- (void) DoNewWindow();
-
- else if (theItem == kOpenMenuItem)
- DoOpen();
-
- else if (theItem == kCloseMenuItem)
- DoCloseWindow(FrontWindow());
-
- else if (theItem == kQuitMenuItem)
- DoQuit();
-
- break;
-
- }
- HiliteMenu(0); // unhilight menu title
- }
-
-
- /***************************************************
- * finally, the main program and event loop
- ***************************************************/
-
- main()
- {
- OSErr retCode;
- long gestResponse;
- Boolean canRunFlag;
-
-
- // initialize the toolbox
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- InitCursor();
- FlushEvents(everyEvent,0);
- MaxApplZone();
-
- // can we run? let's be optimistic
- canRunFlag = true;
-
- // are the Apple Event and Drag managers available?
- // they simply must be
-
- retCode = Gestalt(gestaltAppleEventsAttr, &gestResponse);
- if (retCode != noErr ||
- (gestResponse & (1 << gestaltAppleEventsPresent)) == 0)
-
- canRunFlag = false;
-
- retCode = Gestalt(gestaltDragMgrAttr, &gestResponse);
- if (retCode != noErr ||
- (gestResponse & (1 << gestaltDragMgrPresent)) == 0)
-
- canRunFlag = false;
-
- if (!canRunFlag) ExitToShell(); // an alert would be nicer
-
-
- // use Gestalt to find out what the world is like
- // in particular, check for Color QuickDraw
-
- retCode = Gestalt(gestaltQuickdrawVersion, &gestResponse);
- if (retCode != noErr || gestResponse < 0x0100)
- gHasColorQuickdrawFlag = false;
- else
- gHasColorQuickdrawFlag = true;
-
-
- // now let's initialize everything and install the
- // drag and Apple event handlers
-
- // initialize application globals
-
- gQuitFlag = false;
- gWindowCounter = 0;
-
- // install Apple event handlers
- (void) InstallAppleEventHandlers();
-
- // make the menus
- CreateMenus();
-
- // authenticate the user
- DoAuthentication();
-
- // main event loop
-
- while (!gQuitFlag) {
-
- ProcessEvents();
-
- }
-
- // Good night
- }
-
-
- void ProcessEvents(void)
- {
- EventRecord mainEventRec;
- Boolean eventFlag;
-
- WindowPtr whichWindow;
- Rect tempRect;
-
- eventFlag = WaitNextEvent(everyEvent, &mainEventRec, 60*60*60, nil);
-
- switch(mainEventRec.what) {
-
- case mouseDown:
- switch (FindWindow(mainEventRec.where, &whichWindow)) {
-
- case inSysWindow: // desk accessory window
- SystemClick(&mainEventRec, whichWindow);
- break;
-
- case inMenuBar:
- DoMenuCommand(MenuSelect(mainEventRec.where));
- break;
-
- case inDrag:
- tempRect = qd.screenBits.bounds;
- DragWindow(whichWindow, mainEventRec.where, &tempRect);
- break;
-
- case inGoAway:
- if (TrackGoAway(whichWindow, mainEventRec.where))
- DoCloseWindow(whichWindow);
- break;
-
- case inContent:
-
- // check to see if the user is starting a drag
- if (WaitMouseMoved(mainEventRec.where))
-
- // if so, do the drag magic
- DoWindowContentDrag(whichWindow, &mainEventRec);
-
- else if (whichWindow != FrontWindow())
- SelectWindow(whichWindow);
- break;
- }
- break;
-
- case updateEvt:
-
- whichWindow = (WindowPtr) mainEventRec.message;
-
- if ( ((WindowPeek)whichWindow)->windowKind != dialogKind )
- {
- SetPort(whichWindow);
- BeginUpdate(whichWindow);
-
- EraseRect(&whichWindow->portRect);
- DrawWindow(whichWindow);
-
- EndUpdate(whichWindow);
- }
- break;
-
- case keyDown:
- case autoKey:
- if (mainEventRec.modifiers & cmdKey)
- DoMenuCommand(MenuKey(mainEventRec.message & charCodeMask));
- break;
-
- case kHighLevelEvent:
- DoHighLevelEvent(&mainEventRec);
- break;
-
- // a real app should handle all of these events.
- // Since the code is in Inside Mac:Mac Toolbox Essentials,
- // you really have no excuse for not supporting all the
- // standard low-level events
-
-
-
- // however, this is just a sample program, so I have an excuse
-
- case activateEvt:
- case osEvt:
- case diskEvt:
- case mouseUp:
- break;
- }
- }
-
-
-
-
- /*******************************************************************************
- **
- ** Keith Rollin's utility for using GetKeys from C
- ** returns true if the Key with the given KeyCode is down
- */
- #pragma segment Main
- Boolean KeyIsDown(short keyCode)
- {
- union {
- KeyMap asMap;
- unsigned char asBytes[16];
- } myMap;
-
- GetKeys(myMap.asMap);
- return ((myMap.asBytes[keyCode >> 3] >> (keyCode & 0x07)) & 1) != 0;
- }
-
-